package com.jeasonzhao.commons.parser.lex;

import com.jeasonzhao.commons.basic.StringCollection;
import com.jeasonzhao.commons.basic.StringPair;
import com.jeasonzhao.commons.basic.StringPairCollection;
import com.jeasonzhao.commons.utils.Algorithms;

public class LexTokenizerConfig // implements Cloneable
{
    private CharCollection m_aryNamePrefixes = null;
    private CharCollection m_aryNameChars = null;
    //Long name delimiters
    private StringCollection m_cLongNameDelimiter = null;
    //Name-value pairs indicate block-comments
    private StringPairCollection m_BlockComments = null;
    //Strings indicate a line comment
    private StringCollection m_LineComment = null;
    //Special groups, such as "<<","||","&&" and so on.
    private StringCollection m_specialGroups = null;
    //Name-value pairs indicate special-name group, for example "<name>"
    //"[name]" and so on.
    private StringPairCollection m_specialNamePair = null;
    //A character at the begin of lines indicates that this line
    //must be concatenated with the closed previous line.
    private char m_cMultiLineStringPrefix = LexTokenizer.END;
    //A character at end of lines indicates that the colsed line
    //must be concatenated with the current line.
    private char m_cMultiLineStringSuffix = LexTokenizer.END;
    //Does treat percentage sign as a specail character.
    //If true, "1%" should be parsed as a number.
    //Oterwise, it should be parser as a number '1' and a
    //special character '%'
    private boolean m_isUsingPercentSign = false;

    public LexTokenizerConfig()
    {
    }

//    //Do not ask me why I do this clone method manually!!!
//    public Object clone()
//    {
//        LexTokenizerConfig cfg = new LexTokenizerConfig();
//        if(null != this.m_aryNamePrefixes)
//        {
//            cfg.m_aryNamePrefixes = new CharCollection();
//            for(int n = 0;n < m_aryNamePrefixes.size();n++)
//            {
//                cfg.m_aryNamePrefixes.add(m_aryNamePrefixes.get(n));
//            }
//        }
//
//        if(null != this.m_aryNameChars)
//        {
//            cfg.m_aryNameChars = new CharCollection();
//            for(int n = 0;n < m_aryNameChars.size();n++)
//            {
//                cfg.m_aryNameChars.add(m_aryNameChars.get(n));
//            }
//        }
//        if(null != this.m_cLongNameDelimiter)
//        {
//            cfg.m_cLongNameDelimiter = new StringCollection();
//            for(int n = 0;n < this.m_cLongNameDelimiter.size();n++)
//            {
//                cfg.m_cLongNameDelimiter.add(m_cLongNameDelimiter.get(n));
//            }
//        }
//
//        if(null != this.m_LineComment)
//        {
//            cfg.m_LineComment = new StringCollection();
//            for(int n = 0;n < this.m_LineComment.size();n++)
//            {
//                cfg.m_LineComment.add(m_LineComment.get(n));
//            }
//        }
//        if(null != this.m_specialGroups)
//        {
//            cfg.m_specialGroups = new StringCollection();
//            for(int n = 0;n < this.m_specialGroups.size();n++)
//            {
//                cfg.m_specialGroups.add(m_specialGroups.get(n));
//            }
//        }
//
//        if(null != this.m_specialNamePair)
//        {
//            cfg.m_specialNamePair = new StringPairCollection();
//            for(int n = 0;n < this.m_specialNamePair.size();n++)
//            {
//                cfg.m_specialNamePair.add(new StringPair(m_specialNamePair.get(n)));
//            }
//        }
//
//        if(null != this.m_BlockComments)
//        {
//            cfg.m_BlockComments = new StringPairCollection();
//            for(int n = 0;n < this.m_BlockComments.size();n++)
//            {
//                cfg.m_BlockComments.add(new StringPair(m_BlockComments.get(n)));
//            }
//        }
//        cfg.m_cMultiLineStringPrefix = this.m_cMultiLineStringPrefix;
//        cfg.m_cMultiLineStringSuffix = this.m_cMultiLineStringSuffix;
//        cfg.m_isUsingPercentSign = this.m_isUsingPercentSign;
//        return cfg;
//    }

    private static final StringCollection getStringCollectionFromArray(String[] ary)
    {
        if(null == ary)
        {
            return null;
        }
        else
        {
            StringCollection ret = null;
            java.util.HashSet<String> set = new java.util.HashSet<String>();
            for(int n = 0;null != ary && n < ary.length;n++)
            {
                String s = ary[n];
                if(s == null || s.trim().length() < 1 || set.contains(s))
                {
                    continue;
                }
                set.add(s);
                if(null == ret)
                {
                    ret = new StringCollection();
                }
                ret.add(s);
            }
            return ret;
        }
    }

    private static final StringPairCollection getPairCollectionFromArray(StringPair[] ary)
    {
        if(null == ary)
        {
            return null;
        }
        else
        {
            StringPairCollection ret = new StringPairCollection();
            java.util.HashSet<String> keys = new java.util.HashSet<String>();
            for(int n = 0;n < ary.length;n++)
            {
                StringPair p = ary[n];
                if(null == p
                   || Algorithms.isEmpty(p.getFirst())
                   || Algorithms.isEmpty(p.getSecond())
                   || keys.contains(p.getFirst().trim())
                   || keys.contains(p.getSecond().trim()))
                {
                    continue;
                }
                keys.add(p.getFirst().trim());
                keys.add(p.getSecond().trim());
                StringPair pNew = new StringPair(p.getFirst().trim(),p.getSecond().trim());
                ret.add(pNew);
            }
            ret = null == ret || ret.size() < 1 ? null : ret;
            return ret;
        }
    }

    public void setNamePrefixes(char ...ary)
    {
        m_aryNamePrefixes = null == ary || ary.length < 1 ? null : CharCollection.from(ary);
        if(m_aryNamePrefixes != null && m_aryNamePrefixes.size() < 1)
        {
            m_aryNamePrefixes = null;
        }
    }

    public void setNameExtraCharacter(char ...ary)
    {
        m_aryNameChars = null == ary || ary.length < 1 ? null : CharCollection.from(ary);
        if(m_aryNameChars != null && m_aryNameChars.size() < 1)
        {
            m_aryNameChars = null;
        }
    }

    public boolean isNameCharacter(char c)
    {
        return Character.isLetter(c)
            || Character.isDigit(c)
            || isNamePrefix(c)
            || (null == m_aryNameChars ? false : m_aryNameChars.contains(c))
            ;
    }

    public boolean isNamePrefix(char c)
    {
        return
            Character.isLetter(c)
            || (null == m_aryNamePrefixes ? false : m_aryNamePrefixes.contains(c))
            ;
    }

    public void setLongNameDelimiters(String[] ary)
    {
        this.m_cLongNameDelimiter = getStringCollectionFromArray(ary);
    }

    public StringCollection getLongNameDelimiters()
    {
        return this.m_cLongNameDelimiter;
    }

    public void setCommentBlockPairs(StringPair[] ary)
    {
        m_BlockComments = getPairCollectionFromArray(ary);
    }

    public StringPairCollection getCommentBlockPairs()
    {
        return m_BlockComments;
    }

    public void setLineCommentFlags(String[] ary)
    {
        this.m_LineComment = getStringCollectionFromArray(ary);
    }

    public StringCollection getLineComnmentFlags()
    {
        return this.m_LineComment;
    }

    public void setSpecialSymbols(String[] ary)
    {
        this.m_specialGroups = getStringCollectionFromArray(ary);
    }

    public StringCollection getSpecialSymbols()
    {
        return this.m_specialGroups;
    }

    public void setSpecialNamePairs(StringPair[] ary)
    {
        m_specialNamePair = getPairCollectionFromArray(ary);
    }

    public StringPairCollection getSpecialNamePairs()
    {
        return m_specialNamePair;
    }

    public char getMultiLineStringPrefix()
    {
        return m_cMultiLineStringPrefix;
    }

    public void setMultiLineStringPrefix(char c)
    {
        m_cMultiLineStringPrefix = c;
    }

    public char getMultiLineStringSuffix()
    {
        return m_cMultiLineStringSuffix;
    }

    public void setMultiLineStringSuffix(char c)
    {
        m_cMultiLineStringSuffix = c;
    }

    public boolean isUsingPrecentSign()
    {
        return m_isUsingPercentSign;
    }

    public void setUsingPrecentSign(boolean b)
    {
        m_isUsingPercentSign = b;
    }

    public void setLongNameDelimiters(String string)
    {
        this.setLongNameDelimiters(new String[]
                                   {string});
    }

    public void setLineCommentFlags(String string)
    {
        this.setLineCommentFlags(new String[]
                                 {string});
    }

    public void setCommentBlockPairs(StringPair stringPair)
    {
        this.setCommentBlockPairs(new StringPair[]
                                  {stringPair});
    }

    public void setSpecialNamePairs(StringPair stringPair)
    {
        this.setSpecialNamePairs(new StringPair[]
                                 {stringPair});
    }

}
